package yartiss.engine.simulation.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

import yartiss.engine.simulation.IEnergyProfile;
import yartiss.engine.simulation.ISchedulingPolicy;
import yartiss.engine.simulation.SimulationParameters;
import yartiss.engine.simulation.energy.profiles.EnergyProfileFactory;
import yartiss.engine.simulation.scheduling.policies.SchedulingPolicyFactory;
import yartiss.engine.simulation.system.ITask;
import yartiss.engine.simulation.system.ITaskSet;
import yartiss.engine.simulation.system.schedulable.SchedulableFactory;

public class DefaultParamsParser {

	/**
	 * 
	 * @param f
	 * @return
	 * @throws FileNotFoundException
	 */
	public static SimulationParameters parse(InputStream in)
			throws Exception {
		Scanner s = new Scanner(in);
		SimulationParameters parameters = parse(s);
		s.close();
		return parameters;
	}
	
	public static SimulationParameters parseXml(InputStream in) throws Exception{
		XmlFromFileReader reader = new XmlFromFileReader(in);
		SimulationParameters parameters = reader.readDataSet();
		return parameters;
	}

	/**
	 * Use XmlFileReader as a default and only parser for now!
	 * 
	 * @param in
	 *            input stream of the source file
	 * @param policy
	 *            scheduling policy
	 * @param simulationEnd
	 *            maximum simulation period
	 * @returns simulation parameters
	 * @throws FileNotFoundException
	 */
	public static SimulationParameters parse(InputStream in,
			ISchedulingPolicy policy, int simulationEnd, int nbProc)
			throws ParserConfigurationException, SAXException,
			FileNotFoundException, IOException {

		int[] energyParams = { 1000, 1000, 0, 1000 };
		IEnergyProfile energyProfile = EnergyProfileFactory.getInstance(
				"defaultEnergyProfile", energyParams);

		XmlFileReader reader = new XmlFileReader(in);
		ITaskSet tasks = policy.createTaskSet();
		// Test the first taskset only!
		 tasks.addTasks(reader.readTasksets().get(0));
//		System.out.println("reading tasks:");
//		for (List<ITask> tasks1 : reader.readTasksets()) {
//			System.out.println("taskset");
//			for (ITask iTask : tasks1) {
//				GraphTask graph = (GraphTask) iTask;
//				System.out.println("graph: "+graph.toString());
//				for (SubTask sub : graph.getSubtasks()) {
//					System.out.println("subtask: " + sub.toString());
//					for (SubTask child : sub.getChildrenTasks()) {
//						System.out.println("\tchild: " + child.toString());
//					}
//					for (SubTask parent : sub.getParentTasks()) {
//						System.out.println("\tparent: " + parent.toString());
//					}
//					System.out.println("************");
//				}
//				System.out.println("----------------");
//			}
//		}

		return new SimulationParameters(policy, simulationEnd, energyProfile,tasks, nbProc, true);
	}

	public static SimulationParameters parse(Scanner s) {
		String firstLine = s.nextLine();
		List<Integer> parameters = null;
		String[] words = firstLine.split(" ");
		if (words.length > 1) {
			parameters = new ArrayList<Integer>();
			for (int i = 1; i < words.length; i++)
				parameters.add(Integer.parseInt(words[i]));
		}
		ISchedulingPolicy policy = SchedulingPolicyFactory
				.getInstance(words[0]);
		if (parameters != null)
			policy.setParameters(parameters);

		ITaskSet tasks = policy.createTaskSet();

		words = s.nextLine().split(" ");
		int simulationEnd = Integer.parseInt(words[0]);
		int nbProc = 1;
		if (words.length > 1)
			nbProc = Integer.parseInt(words[1]);
		String[] energyProfileLine = s.nextLine().split(" ");
		int[] energyParams = new int[energyProfileLine.length];
		for (int i = 0; i < energyParams.length; i++) {
			energyParams[i] = Integer.parseInt(energyProfileLine[i]);
		}
		IEnergyProfile energyProfile = EnergyProfileFactory.getInstance(
				"defaultEnergyProfile", energyParams);

		int nbTasks = s.nextInt();
		for (int i = 0; i < nbTasks; i++)
			if (!tasks.addTask(SchedulableFactory.newInstance("simple",
					s.nextInt(), s.nextInt(), s.nextInt(), s.nextInt(),
					s.nextInt(), s.nextInt())))
				System.err.println("Warning : two tasks with same priority");

		return new SimulationParameters(policy, simulationEnd, energyProfile,tasks, nbProc, true);
	}

	/**
	 * 
	 * @param path
	 * @return
	 * @throws Exception 
	 * @throws FileNotFoundException
	 */
	public static SimulationParameters parse(String path) throws FileNotFoundException, Exception
			{
		return parse(new FileInputStream(new File(path)));
	}

	/**
	 * 
	 * @param config
	 * @param file
	 * @throws IOException
	 */
	public static void write(SimulationParameters config, String file)
			throws IOException {
		Writer writer = new FileWriter(file);
		write(config, writer);
		writer.close();
	}

	/**
	 * 
	 * @param config
	 * @param writer
	 * @throws IOException
	 */
	public static void write(SimulationParameters config, Writer writer)
			throws IOException {
		writer.write(config.getSchedulingPolicy().getPolicyName());
		if (config.getSchedulingPolicy().getParameters() != null) {
			for (Integer param : config.getSchedulingPolicy().getParameters()) {
				writer.write(" " + param);
			}
		}
		writer.write("\n" + config.getSimulationEnd() + " "
				+ config.getNbProc() + "\n");

		writer.write(config.getEnergyProfile().getPowerRate() + " "
				+ config.getEnergyProfile().getMaxEnergyLevel() + " "
				+ config.getEnergyProfile().getMinEnergyLevel() + " "
				+ config.getEnergyProfile().getStartEnergyLevel() + "\n");

		writer.write(config.getTaskSet().getAllTasksCount() + "\n");

		for (ITask task : config.getTaskSet()) {
			writer.write(task.getFirstRelease() + " " + task.getWcet() + " "
					+ task.getWcee() + " " + task.getPeriod() + " "
					+ task.getDeadline() + " " + task.getPriority() + "\n");
		}

		writer.write("\n\n\n");
	}

}
